﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Minestorm.Evolved.IoC;

namespace Minestorm.Evolved.Scenes
{
    public class GraphicsState
    {
        public GraphicsState(GraphicsDevice graphics, GraphicsStates states)
        {
            SavedStates = states;

            if ((states & GraphicsStates.DepthStencilState) > 0)
                DepthStencilState = graphics.DepthStencilState;

            if ((states & GraphicsStates.RasterizerState) > 0)
                RasterizerState = graphics.RasterizerState;

            if ((states & GraphicsStates.BlendState) > 0)
                BlendState = graphics.BlendState;
        }

        public void Restore(GraphicsDevice graphics, GraphicsStates graphicStates)
        {
            if ((graphicStates & GraphicsStates.DepthStencilState) > 0 && (SavedStates & GraphicsStates.DepthStencilState) > 0)
                graphics.DepthStencilState = DepthStencilState;

            if ((graphicStates & GraphicsStates.RasterizerState) > 0 && (SavedStates & GraphicsStates.RasterizerState) > 0)
                graphics.RasterizerState = RasterizerState;

            if ((graphicStates & GraphicsStates.BlendState) > 0 && (SavedStates & GraphicsStates.BlendState) > 0)
                graphics.BlendState = BlendState;
        }

        public GraphicsStates SavedStates { get; private set; }

        public DepthStencilState DepthStencilState { get; private set; }
        public RasterizerState RasterizerState { get; private set; }
        public BlendState BlendState { get; private set; }
    }

    [Flags]
    public enum GraphicsStates
    {
        DepthStencilState = 1,
        RasterizerState = 2,
        BlendState = 4,
        All = ~0
    }

    public abstract class SceneObject
    {
        public virtual IObjectFactory ObjectFactory { get; set; }
        public virtual GraphicsDevice GraphicsDevice { get; set; }
        public virtual SpriteBatch SpriteBatch { get; set; }
        public virtual Scene Scene { get; set; }

        private GraphicsState _savedGraphicsState = null;

        protected void SaveGraphicsState(GraphicsStates states)
        {
            _savedGraphicsState = new GraphicsState(GraphicsDevice, states);
        }

        protected void RestoreGraphicsState(GraphicsStates states)
        {
            if (_savedGraphicsState == null)
                return;

            _savedGraphicsState.Restore(GraphicsDevice, states);
        }

        protected void RestoreGraphicsState()
        {
            RestoreGraphicsState(GraphicsStates.All);
        }

        public virtual void LoadContent() { }

        public virtual void UnloadContent() { }

        public virtual void Update(GameTime gameTime) { }

        public virtual void HandleInput(InputState inputState) { }

        public virtual void Draw(GameTime gameTime) { }

        public virtual bool IsInViewFrustum(BoundingSphere sphere)
        {
            return Scene.Camera.IsInViewFrustum(sphere);
        }

        public virtual bool IsInViewFrustum(BoundingBox box)
        {
            return Scene.Camera.IsInViewFrustum(box);
        }
    }
}
